using Abc.Core;
using Abc.Core.Entities;

using Furion.DatabaseAccessor;
using Furion.DependencyInjection;

using Mapster;

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;

using Tool;

namespace Abc.Application
{
    /// <summary>
    /// 用户表
    /// </summary>
    [ApiDescriptionSettings(Name = "User")]
    //[Injection(Proxy = typeof(LogDispatchProxy))]
    [ServiceFilter(typeof(ApiActionFilterAttribute))]
    public class UserService : IUserService, ITransient
    {
        private readonly ILogger<UserService> _logger;
        private readonly IRepository<User> _userRepository;

        private readonly ICacheService _cacheService;
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IRepository<Menu> _menuRepository;
        private readonly IHtAdminManager _htAdminManager;
        public UserService(ILogger<UserService> logger
        , IRepository<User> userRepository
        , ICacheService cacheService
        , IRepository<Menu> menuRepository
        , IHttpContextAccessor httpContextAccessor
        , IHtAdminManager htAdminManager)
        {
            _logger = logger;
            _userRepository = userRepository;
            _cacheService = cacheService;
            _menuRepository = menuRepository;
            _httpContextAccessor = httpContextAccessor;
            _htAdminManager = htAdminManager;
        }


        /// <summary>
        /// 新增或更新一条
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<ResultData<string>> InsertOrUpdate(UserInput input)
        {
            var resultdata = new ResultData<string>();
            var roleids = input.RoleIds.ToIntList();
            if (input.Id > 0)
            {
                #region 修改

                var dbentity = await _userRepository.Include(o => o.UserRoles).FirstOrDefaultAsync(o => o.Id == input.Id);
                input.Adapt(dbentity);
                if (!string.IsNullOrWhiteSpace(input.Pwd))
                {
                    dbentity.Pwd = input.Pwd.ToPBKDF2();
                }

                foreach (var userrole in dbentity.UserRoles.ToList())
                {
                    if (roleids.All(o => o != userrole.RoleId))
                    {
                        dbentity.UserRoles.Remove(userrole);
                    }
                }
                foreach (var roleid in roleids)
                {
                    if (dbentity.UserRoles.Any(o => o.RoleId == roleid)) continue;
                    dbentity.UserRoles.Add(new UserRole() { RoleId = roleid });
                }
                await _userRepository.UpdateNowAsync(dbentity);

                #endregion 修改
            }
            else
            {
                #region 新增

                var addentity = input.Adapt<User>();
                addentity.UserRoles = new List<UserRole>();
                foreach (var roleid in roleids)
                {
                    addentity.UserRoles.Add(new UserRole() { RoleId = roleid });
                }
                addentity.Pwd = input.Pwd?.ToPBKDF2();
                addentity.IsEnable = true;
                var newEntity = await _userRepository.InsertNowAsync(addentity);

                #endregion 新增
            }
            resultdata.Succeeded = true;
            resultdata.Errors = "成功";
            return resultdata;
        }

        /// <summary>
        /// 删除一条
        /// </summary>
        /// <param name="id"></param>
        public async Task<ResultData<string>> Delete(int id)
        {
            var resultdata = new ResultData<string>();
            var user = await _userRepository.FirstOrDefaultAsync(o => o.Id == id);
            if (user != null)
            {
                await _userRepository.DeleteNowAsync(user);
            }

            resultdata.Succeeded = true;
            resultdata.Errors = "成功";
            return resultdata;
        }

        /// <summary>
        /// 批量删除
        /// </summary>
        /// <param name="ids"></param>
        public async Task<ResultData<string>> BatchDelete(string ids)
        {
            var resultdata = new ResultData<string>();
            var idtemps = ids.ToIntList();
            var user = _userRepository.Where(o => idtemps.Any(a => a == o.Id)).ToList();
            await _userRepository.DeleteNowAsync(user);

            resultdata.Succeeded = true;
            resultdata.Errors = "成功";
            return resultdata;
        }

        /// <summary>
        /// 查询一条[跟踪实体]
        /// </summary>
        /// <param name="id"></param>
        public async Task<UserOut> Get(int id)
        {
            var entity = await _userRepository.DetachedEntities.Include(o => o.Roles).FirstOrDefaultAsync(o => o.Id == id);
            return entity.Adapt<UserOut>();
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="searchQuery"></param>
        /// <returns></returns>
        public async Task<PagedListToLayui<UserOut>> GetAllByPageToLayui(UserQuery searchQuery)
        {
            var queryable = _userRepository.DetachedEntities.Where(o => o.UserType != UserType.系统维护);
            if (!string.IsNullOrWhiteSpace(searchQuery.KeyWords))
            {
                var kw = searchQuery.KeyWords.ToLower();
                queryable = queryable.Where(o => o.Account.Contains(kw)
                                               || o.Nick.Contains(kw)
                                               || o.Email.Contains(kw)
                                               || o.Phone.Contains(kw));
            }

            if (searchQuery.UserType.HasValue)
            {
                if (searchQuery.UserType.Value != UserType.系统维护)
                {
                    queryable = queryable.Where(o => o.UserType == searchQuery.UserType.Value);
                }
            }

            var pageResult = queryable.OrderByDescending(o => o.Id).ProjectToType<UserOut>();
            return await pageResult.ToPagedListToLayuiAsync(searchQuery.Page, searchQuery.Limit);
        }

        /// <summary>
        /// 设置状态
        /// </summary>
        /// <param name="id"></param>
        /// <param name="state"></param>
        /// <param name="field">字段名</param>
        /// <returns></returns>
        public async Task<ResultData<string>> SetState(int id, bool state, string field)
        {
            var resultdata = new ResultData<string>();
            var entity = await _userRepository.FirstOrDefaultAsync(o => o.Id == id);

            switch (field.ToLower())
            {
                case "isenable":
                    {
                        entity.IsEnable = state;
                    }
                    break;

                case "istest":
                    {
                        entity.IsTest = state;
                    }
                    break;
                //case "isdeleted":
                //    {
                //        entity.IsDeleted = state;
                //    }
                //    break;
                default:
                    break;
            }

            resultdata.Succeeded = true;
            return resultdata;
        }

        /// <summary>
        /// 获取菜单列表
        /// </summary>
        /// <returns></returns>
        public async Task<List<PearMenuItem>> GetMenus()
        {
            //var menus = new List<PearAdminMenuitemDto>();
            var dbmenus = await _menuRepository.DetachedEntities
.Where(o => o.IsEnable && o.IsShow)
.Select(o => new PearMenuInput() { MenuType = o.MenuType, MId = o.MId, PMId = o.PMId, Name = o.Name, Icon = o.Icon, Sort = o.Sort, Url = o.Url }).ToListAsync();
            var rmenus = dbmenus.GetMenus(pid: "");
            return rmenus;
        }

        /// <summary>
        /// 管理登陆
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<ResultData<UserOut>> Login(UserLoginInput input)
        {
            var resultdata = new ResultData<UserOut>();

            var pwd = input.PassWord.ToPBKDF2();
            var dbmodel = await _userRepository.Include(o => o.Roles).ThenInclude(o => o.Permissions)
.FirstOrDefaultAsync(o => (o.UserType == UserType.系统维护 || o.UserType == UserType.超级管理员 || o.UserType == UserType.管理员) && o.Account == input.Account);
            if (dbmodel == null)
            {
                resultdata.Errors = "账号或密码错误";
                return resultdata;
            }

            if (!input.PassWord.ToPBKDF2Compare2(dbmodel.Pwd))
            {
                resultdata.Errors = "账号或密码错误";
                return resultdata;
            }

            dbmodel.LastLoginTime = DateTimeOffset.Now;

            // var httpContextAccessor = App.GetService<IHttpContextAccessor>();

            #region 日志

            //var ip = _httpContextAccessor?.HttpContext?.GetLocalIpAddressToIPv4();
            //var newlog = new WebLog()
            //{
            //    CreationTime = DateTimeOffset.Now,
            //    RemoteAddr = ip,
            //    RequestUrl = _httpContextAccessor?.HttpContext?.Request?.Path,
            //    Par1 = _httpContextAccessor?.HttpContext?.Request?.Headers["User-Agent"].ToString(),
            //    Type = "管理员登录",
            //    LogContent = $"登陆账号：{dbmodel.Account} 登陆账号ID：{dbmodel.Id} IP:{_httpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString()}"

            //};

            //_userRepository.Change<WebLog>().Insert(newlog);

            #endregion 日志

            #region claims

            var identity = new
                ClaimsIdentity(AuthorizeType.AdminAuthenticationScheme);//一定要声明AuthenticationScheme
            identity.AddClaim(new Claim(ClaimTypes.Name, dbmodel.Nick.ToString()));
            identity.AddClaim(new Claim(ClaimTypes.Sid, dbmodel.Id.ToString()));
            identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, dbmodel.Account.ToString()));

            //if (input.Remember)
            //{
            ///记住我
            await _httpContextAccessor.HttpContext.SignInAsync(identity.AuthenticationType,
                new ClaimsPrincipal(identity),
                new AuthenticationProperties
                {
                    IsPersistent = input.Remember,//false 览器关闭时清除会话cookie
                    RedirectUri = "/HtAdmin/Home/Index",
                });
            //}
            //else
            //{
            //    //浏览器关闭，cookie失效
            //    await _httpContextAccessor.HttpContext.SignInAsync(identity.AuthenticationType,
            //                       new ClaimsPrincipal(identity),
            //                       new AuthenticationProperties
            //                       {
            //                           IsPersistent = false,//浏览器关闭时清除会话cookie
            //                           RedirectUri = "/HtAdmin/Home/Index",
            //                       });
            //}
            #endregion claims

            resultdata.Data = dbmodel.Adapt<UserOut>();
            resultdata.Succeeded = true;
            resultdata.Errors = "登陆成功";

            dbmodel.SetMemoryCache($"Admin_{dbmodel.Id}", new Microsoft.Extensions.Caching.Memory.MemoryCacheEntryOptions()
            {
                SlidingExpiration = TimeSpan.FromMinutes(30),//滑动过期时间
            });
            // _memoryCache.Set($"Admin_{dbmodel.Id}", dbmodel.Roles);

            return resultdata;
        }


        /// <summary>
        /// 获取当前登陆用户
        /// </summary>
        /// <returns></returns>
        public async Task<UserOut> GetLoginUser()
        {
            var userid = _htAdminManager.UserId;
            var user = await _userRepository.FirstOrDefaultAsync(o => o.Id == userid);
            return user.Adapt<UserOut>();
        }

        #region 默认未启用

        ///// <summary>
        ///// 新增一条
        ///// </summary>
        ///// <param name="input"></param>
        ///// <returns></returns>
        //public async Task<ResultData<string>> Insert(UserInput input)
        //{
        //    var resultdata = new ResultData<string>();
        //    var newEntity = await _userRepository.InsertAsync(input.Adapt<User>());
        //
        //    resultdata.Succeeded = true;
        //    resultdata.Errors = "成功";
        //    return resultdata;
        //}
        //
        ///// <summary>
        ///// 更新一条
        ///// </summary>
        ///// <param name="input"></param>
        ///// <returns></returns>
        //public async Task<ResultData<string>> Update(int id,UserInput input)
        //{
        //    var resultdata=new ResultData<string>();
        //    var dbentity = await _userRepository.FindAsync(id);
        //    input.Adapt(dbentity);
        //    await _userRepository.UpdateAsync(dbentity);
        //
        //    resultdata.Succeeded = true;
        //    resultdata.Errors = "成功";
        //    return resultdata;
        //}
        //
        ///// <summary>
        ///// 新增或更新多条
        ///// </summary>
        ///// <param name="inputs"></param>
        ///// <returns></returns>
        //public async Task<ResultData<string>> Inserts(List<UserInput> inputs)
        //{
        //    var resultdata = new ResultData<string>();
        //    var dbaddinputs = inputs.Adapt<List<User>>();
        //    await _userRepository.InsertAsync(dbaddinputs);
        //    resultdata.Succeeded = true;
        //    resultdata.Errors = "成功";
        //    return resultdata;
        //}
        ///// <summary>
        ///// 新增或更新多条
        ///// </summary>
        ///// <param name="inputs"></param>
        ///// <returns></returns>
        //public async Task<ResultData<string>> Updates(List<UserInput> inputs)
        //{
        //    var resultdata = new ResultData<string>();
        //    var ids = inputs.Select(o => o.Id).ToList();
        //    var dbentitys = await _userRepository.Where(u => ids.Any(a => a == u.Id)).ToListAsync();
        //    inputs.Adapt(dbentitys);
        //    await _userRepository.UpdateAsync(dbentitys);
        //
        //    resultdata.Succeeded = true;
        //    resultdata.Errors = "成功";
        //    return resultdata;
        //}
        //
        ///// <summary>
        ///// 新增或更新多条
        ///// </summary>
        ///// <param name="input"></param>
        ///// <returns></returns>
        //public async Task<ResultData<string>> InsertOrUpdates(List<UserInput> inputs)
        //{
        //    var resultdata = new ResultData<string>();
        //    if (inputs.Any(o => o.Id > 0))
        //    {
        //        var updates = inputs.Where(o => o.Id > 0);
        //        var ids = updates.Select(o=>o.Id).ToList();
        //        var dbentity =  _userRepository.Where(o=> ids.Any(a=>a==o.Id));
        //        inputs.Adapt(dbentity);
        //        await  _userRepository.UpdateAsync(dbentity);
        //    }
        //    else
        //    {
        //       var adds = inputs.Where(o => o.Id <= 0);
        //       await _userRepository.InsertAsync(adds.Adapt<List<User>>());
        //
        //    }
        //    resultdata.Succeeded = true;
        //    resultdata.Errors = "成功";
        //    return resultdata;
        //}
        //
        //
        ///// <summary>
        ///// 查询所有
        ///// </summary>
        ///// <returns></returns>
        //public async Task<List<UserDto>> GetAll()
        //{
        //    var entities = _userRepository.DetachedEntities.AsQueryable().ProjectToType<UserDto>();
        //    var datas= await entities.ToListAsync();
        //    datas.SetMemberCache("Table_User");
        //    return datas;
        //}
        ///// <summary>
        ///// 分页查询
        ///// </summary>
        ///// <param name="searchQuery"></param>
        ///// <returns></returns>
        //public async Task<PagedList<UserDto>> GetAllByPage(UserQuery searchQuery)
        //{
        //    //var queryable= _userRepository.DetachedEntities.AsQueryable(tracking:false);
        //    //if (!string.IsNullOrWhiteSpace(searchQuery.KeyWords))
        //    //{
        //    //    var kw = searchQuery.KeyWords.ToLower();
        //    //    queryable = queryable.Where(o => o.No.Contains(kw));
        //    //}
        //    var pageResult = _userRepository.DetachedEntities.AsQueryable().OrderByDescending(o => o.Id).ProjectToType<UserDto>();
        //
        //    return await pageResult.ToPagedListAsync(searchQuery.Page, searchQuery.Limit);
        //}
        //
        //
        //
        //

        #endregion 默认未启用
    }

    public interface IUserService
    {
        /// <summary>
        /// 新增或更新一条
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        Task<ResultData<string>> InsertOrUpdate(UserInput input);

        /// <summary>
        /// 删除一条
        /// </summary>
        /// <param name="id"></param>
        Task<ResultData<string>> Delete(int id);

        /// <summary>
        /// 批量删除
        /// </summary>
        /// <param name="ids"></param>
        Task<ResultData<string>> BatchDelete(string ids);



        /// <summary>
        /// 查询一条
        /// </summary>
        /// <param name="id"></param>
        Task<UserOut> Get(int id);

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="searchQuery"></param>
        /// <returns></returns>
        Task<PagedListToLayui<UserOut>> GetAllByPageToLayui(UserQuery searchQuery);

        /// <summary>
        /// 设置状态
        /// </summary>
        /// <param name="id"></param>
        /// <param name="state"></param>
        /// <param name="field">字段名</param>
        /// <returns></returns>
        Task<ResultData<string>> SetState(int id, bool state, string field);

        /// <summary>
        /// 获取菜单列表
        /// </summary>
        /// <returns></returns>
        Task<List<PearMenuItem>> GetMenus();

        /// <summary>
        /// 管理登陆
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        Task<ResultData<UserOut>> Login(UserLoginInput input);

        /// <summary>
        /// 获取当前登陆用户
        /// </summary>
        /// <returns></returns>
        Task<UserOut> GetLoginUser();

        #region 默认未启用

        ///// <summary>
        ///// 新增一条
        ///// </summary>
        ///// <param name="input"></param>
        ///// <returns></returns>
        //Task<ResultData<string>> Insert(UserInput input);
        //
        ///// <summary>
        ///// 更新一条
        ///// </summary>
        ///// <param name="input"></param>
        ///// <returns></returns>
        //Task<ResultData<string>> Update(int id,UserInput input);
        ///// <summary>
        ///// 新增或更新一条
        ///// </summary>
        ///// <param name="input"></param>
        ///// <returns></returns>
        //Task<ResultData<string>> Inserts(List<UserInput> inputs);
        ///// <summary>
        ///// 新增或更新多条
        ///// </summary>
        ///// <param name="inputs"></param>
        ///// <returns></returns>
        //Task<ResultData<string>> Updates(List<UserInput> inputs);
        ///// <summary>
        ///// 新增或更新多条
        ///// </summary>
        ///// <param name="inputs"></param>
        ///// <returns></returns>
        //Task<ResultData<string>> InsertOrUpdates(List<UserInput> inputs);
        ///// <summary>
        ///// 查询所有
        ///// </summary>
        ///// <returns></returns>
        //Task<List<UserDto>> GetAll();
        ///// <summary>
        ///// 分页查询
        ///// </summary>
        ///// <param name="searchQuery"></param>
        ///// <returns></returns>
        //Task<PagedList<UserDto>> GetAllByPage(UserQuery searchQuery);

        #endregion 默认未启用
    }
}